import json

from sqlalchemy.ext.declarative import DeclarativeMeta


class AlchemyEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # an SQLAlchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                data = obj.__getattribute__(field)
                try:
                    json.dumps(data)  # this will fail on non-encodable values, like other classes
                    fields[field] = data
                except TypeError:
                    pass
            # a json-encodable dict
            return fields

        return json.JSONEncoder.default(self, obj)

    def to_dict(ins):
        table_columns = ins.__table__.c
        l = [column.key for column in table_columns]
        d = {}
        for k, v in ins.__dict__.items():
            if k in l:
                d[k] = str(v) if v is not None else None
        return d
